package net.ming616.nlp.owl.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.annotation.PostConstruct;

import net.ming616.nlp.owl.service.OntologyQueryManager;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.semanticweb.owlapi.model.OWLDataPropertyAssertionAxiom;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.springframework.stereotype.Service;

@Service("ontologyQueryManager")
public class OntologyQueryManagerImpl extends BaseOWLManagerImpl implements
		OntologyQueryManager {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger
			.getLogger(OntologyQueryManagerImpl.class);

	private boolean contain(List<String> literals, List<String> values) {
		boolean result = true;
		for (String value : values) {
			if (!this.contain(literals, value)) {
				result = false;
				break;
			}
		}
		return result;
	}

	private boolean contain(List<String> literals, String value) {
		boolean result = false;
		for (String liberal : literals) {
			if (StringUtils.contains(liberal, value)) {
				result = true;
				break;
			}
		}
		return result;
	}

	// checking whether map contains key-value;
	private boolean contain(Map<String, String> map, String key, String value) {
		boolean result = false;
		for (Entry<String, String> entry : map.entrySet()) {
			if (StringUtils.contains(entry.getKey(), key)
					&& StringUtils.contains(entry.getValue(), value)) {
				result = true;
				break;
			}
		}
		return result;

	}

	/**
	 * query individuals by attribute-value pairs
	 * 
	 * @param attrs
	 * @return
	 */
	public List<OWLNamedIndividual> getIndividualsByAttributeAndValue(
			Map<String, String> attrs) {
		Set<OWLNamedIndividual> individuals = this.ontology
				.getIndividualsInSignature();
		List<OWLNamedIndividual> result = new ArrayList<OWLNamedIndividual>();
		for (OWLNamedIndividual individual : individuals) {
			Set<OWLDataPropertyAssertionAxiom> axioms = this.ontology
					.getDataPropertyAssertionAxioms(individual);
			Map<String, String> propertyMap = new HashMap<String, String>();
			for (OWLDataPropertyAssertionAxiom owlAxiom : axioms) {
				String propertyString = owlAxiom.getProperty()
						.asOWLDataProperty().toString();
				String attributeName = StringUtils.substringAfterLast(
						propertyString, "#");
				OWLLiteral object = owlAxiom.getObject();
				String literal = object.getLiteral();
				propertyMap.put(attributeName, literal);
			}

			boolean flag = true;
			for (Entry<String, String> entry : attrs.entrySet()) {
				if (!this
						.contain(propertyMap, entry.getKey(), entry.getValue())) {
					flag = false;
					break;
				}
			}
			if (flag) {
				result.add(individual);
			}

		}
		return result;
	}

	public List<OWLNamedIndividual> getIndividualsByValues(List<String> values) {
		Set<OWLNamedIndividual> individuals = this.ontology
				.getIndividualsInSignature();
		List<OWLNamedIndividual> result = new ArrayList<OWLNamedIndividual>();
		for (OWLNamedIndividual individual : individuals) {
			Set<OWLDataPropertyAssertionAxiom> axioms = this.ontology
					.getDataPropertyAssertionAxioms(individual);
			List<String> literals = new ArrayList<String>();
			for (OWLDataPropertyAssertionAxiom owlAxiom : axioms) {
				OWLLiteral in = owlAxiom.getObject();
				String literal = in.getLiteral();
				literals.add(literal);
			}
			if (this.contain(literals, values)) {
				result.add(individual);
			}
		}
		return result;
	}

	public String getValueByProperty(String property,
			OWLNamedIndividual individual) {
		String result = "";
		Set<OWLDataPropertyAssertionAxiom> axioms = this.ontology
				.getDataPropertyAssertionAxioms(individual);
		for (OWLDataPropertyAssertionAxiom owlAxiom : axioms) {
			String propertyString = owlAxiom.getProperty().asOWLDataProperty()
					.toString();
			if (StringUtils.contains(propertyString, property)) {
				OWLLiteral object = owlAxiom.getObject();
				String literal = object.getLiteral();
				result = result + literal;
			}
		}
		return result;

	}

	@PostConstruct
	void init() {
		super.init();
	}

}
